#include "globals.h"
#include "errno.h"
#include "types.h"

#include "mm/mm.h"
#include "mm/tlb.h"
#include "mm/mman.h"
#include "mm/page.h"

#include "proc/proc.h"

#include "util/string.h"
#include "util/debug.h"

#include "fs/vnode.h"
#include "fs/vfs.h"
#include "fs/file.h"

#include "vm/vmmap.h"
#include "vm/mmap.h"

/*
 * This function implements the mmap(2) syscall, but only
 * supports the MAP_SHARED, MAP_PRIVATE, MAP_FIXED, and
 * MAP_ANON flags.
 *
 * Add a mapping to the current process's address space.
 * You need to do some error checking; see the ERRORS section
 * of the manpage for the problems you should anticipate.
 * After error checking most of the work of this function is
 * done by vmmap_map(), but remember to clear the TLB.
 */
int
do_mmap(void *addr, size_t len, int prot, int flags,
        int fd, off_t off, void **ret)
{
    KASSERT(NULL && "need modify");
	 KASSERT(NULL != curproc->p_pagedir);
     KASSERT(len > 0);
     KASSERT(!(~(PROT_NONE | PROT_READ | PROT_WRITE | PROT_EXEC) & prot));
     KASSERT((MAP_SHARED & flags) || (MAP_PRIVATE & flags) || (MAP_FIXED & flags) || (MAP_ANON & flags));

    file_t* fptr = fget(fd);
    if(fptr == NULL)
    {
        return -EBADF;
    }
    KASSERT(fptr->f_vnode);
    uint32_t lopage = (uint32_t)PAGE_ALIGN_DOWN(addr);
    uint32_t left = len - PAGE_OFFSET(addr);
    uint32_t npages = left % PAGE_SIZE == 0 ? left / PAGE_SIZE : left / PAGE_SIZE + 1; /*the pages left occupies*/
    npages += 1;  /*plus the page of lopage*/

    int res = vmmap_map(curproc->p_vmmap, fptr->f_vnode, lopage, npages, prot, flags, off, VMMAP_DIR_HILO, NULL);
    if(ret)
        *ret = (void*)res;
    return 0;
}


/*
 * This function implements the munmap(2) syscall.
 *
 * As with do_mmap() it should perform the required error checking,
 * before calling upon vmmap_remove() to do most of the work.
 * Remember to clear the TLB.
 */
int
do_munmap(void *addr, size_t len)
{
    KASSERT(NULL && "need modify");
    KASSERT(len > 0);
    KASSERT(NULL != curproc->p_pagedir);
    uint32_t lopage = (uint32_t)PAGE_ALIGN_DOWN(addr);
    uint32_t left = len - PAGE_OFFSET(addr);
    uint32_t npages = left % PAGE_SIZE == 0 ? left / PAGE_SIZE : left / PAGE_SIZE + 1; /*the pages left occupies*/
    npages += 1;  /*plus the page of lopage*/

    int res = vmmap_remove(curproc->p_vmmap, lopage, npages);

    return res;
}

